﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using PMisuseAn.behaviour.model;
using PMisuseAn.io;

namespace PMisuseAn
{
    /// <summary>
    /// Interaction logic for MitigationReferenceWindow1.xaml
    /// </summary>
    public partial class MitigationReferenceWindow : Window
    {
        AddStateMachineWindow asw_;
        MitigationReferences m_ref_;
        string machineName_;

        public MitigationReferenceWindow(AddStateMachineWindow asw, MitigationReferences m_ref, string machineName, string entityName)
        {
            InitializeComponent();
            asw_ = asw;
            m_ref_ = m_ref;
            machineName_ = machineName;
            this.Title = this.Title + "(" + entityName + ")";
            loadStates();
            loadTransitions();
        }


        public MitigationReferenceWindow(MitigationReferences m_ref, string machineName, string entityName)
        {
            InitializeComponent();
            m_ref_ = m_ref;
            machineName_ = machineName;
            this.Title = this.Title + "(" + entityName + ")";
            loadStates();
            loadTransitions();
        }

        private void remove_state_b_Click(object sender, RoutedEventArgs e)
        {
            ListBoxItem selectedStateItem = (ListBoxItem)state_mitigation_ref_lb.SelectedItem;
            if (selectedStateItem != null)
            {
                StackPanel sp_tag = (StackPanel)selectedStateItem.Tag;
                State selectedState = (State)sp_tag.Tag;
                m_ref_.removeState(selectedState);

                foreach (ContentPresenter c in sp_tag.Children)
                {
                    CheckBox cb = (CheckBox)c.Tag;
                    if (cb != null)
                    {
                        if (cb.IsChecked == true)
                        {
                            PMisuseAn.behaviour.model.Action selectedStateAction = (PMisuseAn.behaviour.model.Action)cb.Tag;
                            m_ref_.removeAction(selectedStateAction);
                        }
                    }
                }
                state_mitigation_ref_lb.Items.Remove(selectedStateItem); 
                states_lb.Items.Add(selectedStateItem);

                updateStateRefSeqIndex();
                
            }
        }

        private void add_state_b_Click(object sender, RoutedEventArgs e)
        {
            ListBoxItem selectedStateItem = (ListBoxItem)states_lb.SelectedItem;
            if (selectedStateItem != null)
            {
                StackPanel sp_tag = (StackPanel)selectedStateItem.Tag;
                State selectedState = (State)sp_tag.Tag;

                int indx = state_mitigation_ref_lb.Items.IndexOf(selectedStateItem);
                selectedState.mitigationSeqRefIndex = indx;

                m_ref_.addState(selectedState);

                foreach (ContentPresenter c in sp_tag.Children)
                {
                    CheckBox cb = (CheckBox)c.Tag;
                    if (cb != null)
                    {
                        if (cb.IsChecked == true)
                        {
                            PMisuseAn.behaviour.model.Action selectedStateAction = (PMisuseAn.behaviour.model.Action)cb.Tag;
                            m_ref_.addAction(selectedStateAction);
                        }
                    }
                }
                states_lb.Items.Remove(selectedStateItem);
                state_mitigation_ref_lb.Items.Add(selectedStateItem);

                updateStateRefSeqIndex();
            }
        }

        public void updateStateRefSeqIndex()
        {
            foreach (ListBoxItem item in state_mitigation_ref_lb.Items)
            {
                if (item != null)
                {
                    int itemIndex = state_mitigation_ref_lb.Items.IndexOf(item);

                    StackPanel sp_tag = (StackPanel)item.Tag;
                    State state = (State)sp_tag.Tag;

                    foreach (State state_ in m_ref_.states)
                    {
                        if (state_.name.Equals(state.name))
                        {
                            state_.mitigationSeqRefIndex = itemIndex;
                            break;
                        }
                    }
                }
            }
        }

        public void updateTransitionRefSeqIndex()
        {
            foreach (ListBoxItem item in transitions_mitigation_lb.Items)
            {
                if (item != null)
                {
                    int itemIndex = transitions_mitigation_lb.Items.IndexOf(item);

                    StackPanel sp_tag = (StackPanel)item.Tag;
                    Transition trans = (Transition)sp_tag.Tag;

                    foreach (Transition trans_ in m_ref_.transitions)
                    {
                        if (trans_.transitionName.Equals(trans.transitionName))
                        {
                            trans_.mitigationSeqRefIndex = itemIndex;
                            break;
                        }
                    }
                }
            }
        }


        private void move_state_ref_item_up_b_Click(object sender, RoutedEventArgs e)
        {
            object selected = state_mitigation_ref_lb.SelectedItem;
            if (selected != null)
            {
                int indx = state_mitigation_ref_lb.Items.IndexOf(selected);
                int totl = state_mitigation_ref_lb.Items.Count;

                if (indx == 0)
                {
                    state_mitigation_ref_lb.Items.Remove(selected);
                    state_mitigation_ref_lb.Items.Insert(totl - 1, selected);
                    state_mitigation_ref_lb.SelectedIndex = totl - 1;
                }
                else
                {
                    state_mitigation_ref_lb.Items.Remove(selected);
                    state_mitigation_ref_lb.Items.Insert(indx - 1, selected);
                    state_mitigation_ref_lb.SelectedIndex = indx - 1;
                }

                updateStateRefSeqIndex();
            }
        }

        private void move_state_ref_item_down_b_Click(object sender, RoutedEventArgs e)
        {
            object selected = state_mitigation_ref_lb.SelectedItem;
            if (selected != null)
            {
                int indx = state_mitigation_ref_lb.Items.IndexOf(selected);
                int totl = state_mitigation_ref_lb.Items.Count;

                if (indx == totl - 1)
                {
                    state_mitigation_ref_lb.Items.Remove(selected);
                    state_mitigation_ref_lb.Items.Insert(0, selected);
                    state_mitigation_ref_lb.SelectedIndex = 0;
                }
                else
                {
                    state_mitigation_ref_lb.Items.Remove(selected);
                    state_mitigation_ref_lb.Items.Insert(indx + 1, selected);
                    state_mitigation_ref_lb.SelectedIndex = indx + 1;
                }

                updateStateRefSeqIndex();
            }
        }

        public int getStateIndex(State state_)
        {
            int index = 0;
            foreach (ListBoxItem item in state_mitigation_ref_lb.Items)
            {                
                if (item != null)
                {
                    int itemIndex = state_mitigation_ref_lb.Items.IndexOf(item);

                    StackPanel sp_tag = (StackPanel)item.Tag;
                    State item_state = (State)sp_tag.Tag;

                    if (item_state.mitigationSeqRefIndex >= state_.mitigationSeqRefIndex)
                    {
                        if (index > itemIndex)
                        {
                            index = itemIndex;
                            if (index < 0)
                                index = 0;
                        }                        
                    }
                    else
                    {
                        index = itemIndex + 1;
                    }

                    //foreach (State state_ in m_ref_.states)
                    //{
                    //    if (state_.name.Equals(state.name))
                    //    {
                    //        state_.mitigationSeqRefIndex = itemIndex;
                    //        break;
                    //    }
                    //}

                    //StackPanel sp_tag = (StackPanel)item.Tag;
                    //State state = (State)sp_tag.Tag;

                    //int mitigationSeqRefIndex = state.mitigationSeqRefIndex;

                    //if (!(state_.name.Equals(state.name)) &&
                    //    (state.mitigationSeqRefIndex >= state_.mitigationSeqRefIndex))
                    //{
                    //    index = state.mitigationSeqRefIndex + 1;
                    //}
                }
            }

            return index;
        }

        public void loadStates()
        {            
            List<State> allExistingStates = MisUseAnObjectsDB.loadAllStates(machineName_, MainWindow.clusterName);
            states_lb.Items.Clear();
            state_mitigation_ref_lb.Items.Clear();
                        
            foreach (State state in m_ref_.states)
            {
                ListBoxItem l = new ListBoxItem();
                StackPanel s = new StackPanel();
                s.Orientation = Orientation.Vertical;
                ContentPresenter c1 = new ContentPresenter();
                c1.Content = state.name;
                s.Children.Add(c1);

                foreach (PMisuseAn.behaviour.model.Action action in state.actions)
                {
                    CheckBox cb = new CheckBox();
                    cb.Content = action.name;
                    cb.Tag = action;
                    foreach (PMisuseAn.behaviour.model.Action a in m_ref_.actions)
                    {
                        if (a.actionID == action.actionID)
                        {
                            cb.IsChecked = true;
                            break;
                        }
                    }
                    ContentPresenter c2 = new ContentPresenter();
                    c2.Content = cb;
                    c2.Tag = cb;

                    s.Children.Add(c2);
                }
                int s_index;
                //bool containsNullSeq = MisUseAnObjectsDB.containsNullStateMitigationReferences(state.name, state.machineName, state.clusterName);
                //if(containsNullSeq == true)
                //{                    
                //    s_index = getStateIndex(state);
                //    state.mitigationSeqRefIndex = s_index;
                //}
                //else{
                //    s_index = state.mitigationSeqRefIndex;
                //}

                s_index = getStateIndex(state);
                
                s.Tag = state;
                s.IsEnabled = false;
                l.Content = s;
                l.Tag = s;

                if (state_mitigation_ref_lb.Items.IsEmpty ||(state_mitigation_ref_lb.Items.Count <= (s_index-1)))
                {
                    state_mitigation_ref_lb.Items.Add(l);
                }
                else
                {
                    state_mitigation_ref_lb.Items.Insert(s_index, l);
                }
            }
            updateStateRefSeqIndex();  

            foreach (State state in allExistingStates)
            {
                bool alreadySelected = false;
                foreach (State st in m_ref_.states)
                {
                    if (st.stateID == state.stateID)
                    {
                        alreadySelected = true;
                    }
                }

                if (!alreadySelected)
                {

                    ListBoxItem l = new ListBoxItem();
                    StackPanel s = new StackPanel();
                    s.Orientation = Orientation.Vertical;
                    ContentPresenter c1 = new ContentPresenter();
                    c1.Content = state.name;
                    s.Children.Add(c1);

                    foreach (PMisuseAn.behaviour.model.Action action in state.actions)
                    {
                        CheckBox cb = new CheckBox();
                        cb.Content = action.name;
                        cb.Tag = action;
                        ContentPresenter c2 = new ContentPresenter();
                        c2.Content = cb;
                        c2.Tag = cb;

                        s.Children.Add(c2);
                    }

                    s.Tag = state;
                    s.IsEnabled = false;
                    l.Content = s;
                    l.Tag = s;
                    l.AddHandler(ListBoxItem.SelectedEvent, new RoutedEventHandler(states_lb_Item_selected));

                    states_lb.Items.Add(l);
                }               
            }
        }

        private void states_lb_Item_selected(object sender, RoutedEventArgs e)
        {
            ListBoxItem cm_i = (ListBoxItem)sender;
            StackPanel sp_tag = (StackPanel)cm_i.Tag;
            State sp_tag_state = (State)sp_tag.Tag;
            sp_tag.IsEnabled = true;

            foreach (ListBoxItem item in states_lb.Items)
            {
                StackPanel sp_tag_item = (StackPanel)item.Tag;
                State s = (State)sp_tag_item.Tag;

                if (!s.name.Equals(sp_tag_state.name))
                {
                    foreach (ContentPresenter c in sp_tag_item.Children)
                    {
                        CheckBox cb = (CheckBox)c.Tag;
                        if (cb != null)
                        {
                            cb.IsChecked = false;
                        }
                    }
                    sp_tag_item.IsEnabled = false;
                }
            }
        }

        private void add_transition_b_Click(object sender, RoutedEventArgs e)
        {
              ListBoxItem selectedStateItem = (ListBoxItem)transitions_lb.SelectedItem;
              if (selectedStateItem != null)
              {
                  StackPanel sp_tag = (StackPanel)selectedStateItem.Tag;
                  Transition selectedTransition = (Transition)sp_tag.Tag;
                  m_ref_.addTransition(selectedTransition);

                  transitions_lb.Items.Remove(selectedStateItem);
                  transitions_mitigation_lb.Items.Add(selectedStateItem);

                  updateTransitionRefSeqIndex();                
              }
        }

        private void remove_transition_b_Click(object sender, RoutedEventArgs e)
        {
            ListBoxItem selectedStateItem = (ListBoxItem)transitions_mitigation_lb.SelectedItem;
            if (selectedStateItem != null)
            {
                StackPanel sp_tag = (StackPanel)selectedStateItem.Tag;
                Transition selectedTransition = (Transition)sp_tag.Tag;
                m_ref_.removeTransition(selectedTransition);

                transitions_mitigation_lb.Items.Remove(selectedStateItem);
                transitions_lb.Items.Add(selectedStateItem);
                updateTransitionRefSeqIndex();                
            }
        }

        public int getTransitionIndex(Transition trans_)
        {
            int index = 0;
            foreach (ListBoxItem item in transitions_mitigation_lb.Items)
            {
                if (item != null)
                {
                    int itemIndex = transitions_mitigation_lb.Items.IndexOf(item);

                    StackPanel sp_tag = (StackPanel)item.Tag;
                    Transition item_trans = (Transition)sp_tag.Tag;

                    if (item_trans.mitigationSeqRefIndex >= trans_.mitigationSeqRefIndex)
                    {
                        if (index > itemIndex)
                        {
                            index = itemIndex;
                            if (index < 0)
                                index = 0;
                        } 
                    }
                    else
                    {
                        index = itemIndex + 1;
                    }

                    //StackPanel sp_tag = (StackPanel)item.Tag;
                    //Transition trans = (Transition)sp_tag.Tag;

                    //int mitigationSeqRefIndex = trans.mitigationSeqRefIndex;

                    //if (!(trans_.transitionName.Equals(trans.transitionName)) &&
                    //    (trans.mitigationSeqRefIndex >= trans_.mitigationSeqRefIndex))
                    //{
                    //    index = trans.mitigationSeqRefIndex + 1;
                    //}
                }
            }

            return index;
        }

        private void move_transition_ref_item_up_b_Click(object sender, RoutedEventArgs e)
        {
            object selected = transitions_mitigation_lb.SelectedItem;
            if (selected != null)
            {
                int indx = transitions_mitigation_lb.Items.IndexOf(selected);
                int totl = transitions_mitigation_lb.Items.Count;

                if (indx == 0)
                {
                    transitions_mitigation_lb.Items.Remove(selected);
                    transitions_mitigation_lb.Items.Insert(totl - 1, selected);
                    transitions_mitigation_lb.SelectedIndex = totl - 1;
                }
                else
                {
                    transitions_mitigation_lb.Items.Remove(selected);
                    transitions_mitigation_lb.Items.Insert(indx - 1, selected);
                    transitions_mitigation_lb.SelectedIndex = indx - 1;
                }

                updateTransitionRefSeqIndex();
            }
        }

        private void move_transition_ref_item_down_b_Click(object sender, RoutedEventArgs e)
        {
            object selected = transitions_mitigation_lb.SelectedItem;
            if (selected != null)
            {
                int indx = transitions_mitigation_lb.Items.IndexOf(selected);
                int totl = transitions_mitigation_lb.Items.Count;

                if (indx == totl - 1)
                {
                    transitions_mitigation_lb.Items.Remove(selected);
                    transitions_mitigation_lb.Items.Insert(0, selected);
                    transitions_mitigation_lb.SelectedIndex = 0;
                }
                else
                {
                    transitions_mitigation_lb.Items.Remove(selected);
                    transitions_mitigation_lb.Items.Insert(indx + 1, selected);
                    transitions_mitigation_lb.SelectedIndex = indx + 1;
                }

                updateTransitionRefSeqIndex();
            }
        }

        public void loadTransitions()
        {
            List<Transition> allExistingStateTransitions = MisUseAnObjectsDB.loadAllStateTransitions(machineName_, MainWindow.clusterName);
            List<Policy> policy_statements = MisUseAnObjectsDB.loadAllPolicyStatementsFull(MainWindow.clusterName);
            
            transitions_lb.Items.Clear();
            transitions_mitigation_lb.Items.Clear();
            
            foreach (Transition trans in m_ref_.transitions)
            {
                string trans_content = trans.transitionName + "(" + trans.startState +
                    "," + trans.endState + "," + trans.associatedEevent + ")";

                ListBoxItem l = new ListBoxItem();
                StackPanel s = new StackPanel();
                s.Orientation = Orientation.Vertical;
                ContentPresenter c1 = new ContentPresenter();
                c1.Content = trans_content;
                s.Children.Add(c1);

                foreach (string p_id in trans.policyIDs)
                {
                    foreach (Policy p in policy_statements)
                    {
                        if (p.id.Equals(p_id))
                        {
                            ContentPresenter c2 = new ContentPresenter();
                            c2.Content = "     " + p.statement;
                            s.Children.Add(c2);
                        }
                    }
                }
                ContentPresenter c3 = new ContentPresenter();
                c3.Content = "     ";
                s.Children.Add(c3);

                int trans_index;
                //bool containsNullSeq = MisUseAnObjectsDB.containsNullTransitionMitigationReferences(trans.transitionName, trans.machineName, trans.clusterName);
                //if(containsNullSeq == true)
                //{                    
                //    trans_index = getTransitionIndex(trans);
                //    trans.mitigationSeqRefIndex = trans_index;
                //}
                //else{
                //    trans_index = trans.mitigationSeqRefIndex;
                //}               

                trans_index = getTransitionIndex(trans);

                s.Tag = trans;

                l.Content = s;
                l.Tag = s;
                
                if (transitions_mitigation_lb.Items.IsEmpty || (transitions_mitigation_lb.Items.Count <= (trans_index - 1)))
                {
                    transitions_mitigation_lb.Items.Add(l);
                }
                else
                {
                    transitions_mitigation_lb.Items.Insert(trans_index, l);
                }
            }
            updateStateRefSeqIndex();  
            
            foreach (Transition trans in allExistingStateTransitions)
            {
                bool alreadySelected = false;
                foreach (Transition t in m_ref_.transitions)
                {
                    if (t.transitionID == trans.transitionID)
                    {
                        alreadySelected = true;
                    }
                }

                if (!alreadySelected)
                {
                    string trans_content = trans.transitionName + "(" + trans.startState +
                        "," + trans.endState + "," + trans.associatedEevent + ")";

                    ListBoxItem l = new ListBoxItem();
                    StackPanel s = new StackPanel();
                    s.Orientation = Orientation.Vertical;
                    ContentPresenter c1 = new ContentPresenter();
                    c1.Content = trans_content;
                    s.Children.Add(c1);

                    foreach (string p_id in trans.policyIDs)
                    {
                        foreach (Policy p in policy_statements)
                        {
                            if (p.id.Equals(p_id))
                            {
                                ContentPresenter c2 = new ContentPresenter();
                                c2.Content = "     " + p.statement;
                                s.Children.Add(c2);
                            }
                        }
                    }
                    ContentPresenter c3 = new ContentPresenter();
                    c3.Content = "     ";
                    s.Children.Add(c3);
                    s.Tag = trans;

                    l.Content = s;
                    l.Tag = s;
                    transitions_lb.Items.Add(l);
                }
            }
        }

        private void state_action_update_b_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
    }
}
